package voxToolkit;

import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.util.ArrayList;

import javax.swing.DefaultListModel;
import javax.swing.JList;

public class VoxListFiles extends VoxList implements KeyListener, MouseListener
{

	private static final long serialVersionUID = 1L;
	ArrayList<String> anterior;
	JList listaArquivos; // lista de arquivos associada
	String filtro = null;
	public String caminhoAtual="";
	
	private VoxContexto contexto;

	/**
	 * Cria um objeto a partir de: um dataModel para compor a lista e um rótulo
	 * que identifica o nome da lista para ser lido pelo sintetizador.
	 * 
	 * @param dataModel
	 * @param rotulo
	 */
	public VoxListFiles( DefaultListModel dataModel, String rotulo )
	{
		super(dataModel, rotulo);
		anterior = new ArrayList<String>();
		addKeyListener(this);
		addMouseListener(this);
		contexto = VoxContexto.instancia();
	}

	/**
	 * Cria um objeto a partir de: um dataModel para compor a lista, um rótulo
	 * que identifica o nome da lista para ser lido pelo sintetizador e um
	 * filtro para o tipo de arquivo a ser aberto.
	 * 
	 * @param dataModel
	 * @param rotulo
	 * @param filtro
	 */
	public VoxListFiles( DefaultListModel dataModel, String rotulo,
			String filtro )
	{
		super(dataModel, rotulo);
		this.filtro = filtro;
		anterior = new ArrayList<String>();
		addKeyListener(this);
		addMouseListener(this);
		contexto = VoxContexto.instancia();
	}

	/**
	 * Adiciona uma listaArquivos para conter os arquivos do diretório corrente
	 * da VoxListFiles
	 * 
	 * @param listaArquivos
	 */
	public void addList ( JList listaArquivos )
	{
		this.listaArquivos = listaArquivos;
	}

	/**
	 * Exibe o conteúdo do nível acima quando for selecionado ".."
	 */
	protected void exibeAcima ()
	{
		
		limpaModels();
		
		//preenche o model de diretórios com o conteúdo de anterior
		for (int i = 0; i < anterior.size(); i++)
		{
			((DefaultListModel) getModel()).addElement(anterior.get(i));
		}
		anterior.clear();
		
		//refaz o caminhoAtual, subindo um nível.
		File camAtual = new File (caminhoAtual);
		caminhoAtual = camAtual.getParent();
		if (caminhoAtual == null) caminhoAtual = "";
		
		File pai = camAtual.getParentFile();
		//System.out.println("...........atual "+camAtual);
		//System.out.println("...........pai "+pai);		
		
		if (pai != null)
		{	

			//adiciona '..' para acessar o nível acima apenas se houver "pai"
			if (!((DefaultListModel) getModel()).get(0).equals(".."))
			{
				((DefaultListModel) this.getModel()).add(0, "..");
			}
			
			//se o pai tem pai, preenche o anterior com os dirs filhos dele
			if (pai.getParentFile() != null)
			{
				File[] dirsacima = pai.getParentFile().listFiles();
				System.out.println("novo anterior: ");
				for (int i = 0; i < dirsacima.length; i++)
				{
					if (dirsacima[i].isDirectory()){
						anterior.add(dirsacima[i].getName());
						System.out.println("--> "+dirsacima[i].getName());
					}
				}
				caminhoAtual+=contexto.separador(); //adiciona separador ao final do caminho
			}
			
			//se o pai não tem pai preenche o anterior com os roots
			else
			{
				File[] f = File.listRoots();
				for (int i = 0; i < f.length; i++)
					anterior.add(f[i].getName());
			}
		}
		else { //se o pai for null adiciona os roots no model
			File[] f = File.listRoots();
			for (int i = 0; i < f.length; i++){
				((DefaultListModel) getModel()).addElement(f[i]);
			}
		}
	}

	private void limpaModels() {
		((DefaultListModel) getModel()).removeAllElements();
		((DefaultListModel) listaArquivos.getModel()).removeAllElements();
	}

	/**
	 * Exibe o conteúdo do nível abaixo quando algum item for selecionado
	 * 
	 * @param indice
	 */
	protected void exibeAbaixo ( int indice )
	{
		anterior.clear();
		
		File arquivoSelecionado = new File(caminhoAtual+getModel().getElementAt(indice).toString());
		System.out.println("arq clicado "+arquivoSelecionado);
		
		if (caminhoAtual.equals(""))
		{
			File[] f = File.listRoots();
			for (int i = 0; i < f.length; i++)
			{
				anterior.add(f[i].getName());
			}

			caminhoAtual = arquivoSelecionado.getPath();
		}
		else
		{
			//adiciona o conteúdo atual em anterior
			for (int i = 0; i < getModel().getSize(); i++)
			{
				if (!getModel().getElementAt(i).toString().equals(".."))
					anterior.add(new File(caminhoAtual+contexto.separador()+getModel().getElementAt(i).toString()).getName());
			}

			caminhoAtual = arquivoSelecionado.getPath()+contexto.separador();
		}
		
		limpaModels();
		
		//adiciona ".." no model para acessar o nível acima 
		((DefaultListModel) getModel()).addElement("..");
		
		//captura os arquivos que estão abaixo do arquivo selecionado
		File[] arquivosAbaixo = arquivoSelecionado.listFiles();
		if (arquivosAbaixo != null)
			for (int i = 0; i < arquivosAbaixo.length; i++)
			{
				//se for diretório, adiciona no model da lista de diretórios
				if (arquivosAbaixo[i].isDirectory())
				{
					((DefaultListModel) getModel()).addElement(arquivosAbaixo[i].getName());
				}
				
				//se não for diretório, adiciona no model da lista de arquivos
				else
				{
					if (filtro != null)
					{
						if (getExtension(arquivosAbaixo[i]).equals(filtro))
							((DefaultListModel) listaArquivos.getModel())
									.addElement(arquivosAbaixo[i].getName());
					}
					else
						((DefaultListModel) listaArquivos.getModel())
								.addElement(arquivosAbaixo[i].getName());
				}
				
			}
	}

	/**
	 * Obtém a extensão do arquivo
	 * 
	 * @param f Arquivo cuja extensão será obtida
	 * @return Extensão do arquivo
	 */
	public String getExtension ( File f )
	{
		String ext = null;
		String s = f.getName();
		int i = s.lastIndexOf('.');

		if (i > 0 && i < s.length() - 1)
			ext = s.substring(i + 1).toLowerCase();
		else
			ext = "";
		return ext;
	}
	
	/**
	 * Captura o caminho do diretório atual da lista e o retorna. 
	 * @return Caminho do diretório atualmente selecionado na lista
	 */
	public String caminhoAtual(){
		return caminhoAtual;
	}

	@Override
	public void keyPressed ( KeyEvent arg0 )
	{
		// TODO Auto-generated method stub

	}

	@Override
	public void keyReleased ( KeyEvent arg0 )
	{
		// TODO Auto-generated method stub

	}

	@Override
	public void keyTyped ( KeyEvent e )
	{
		VoxListFiles lista = (VoxListFiles) e.getSource();
		if (!lista.isSelectionEmpty())
		{
			if (e.getKeyChar() == KeyEvent.VK_ENTER)
			{
				int indice = lista.getSelectedIndex();

				if ((String) lista.getModel().getElementAt(indice).toString() == "..")
				{
					lista.exibeAcima();
				}
				else
				{
					lista.exibeAbaixo(indice);
				}
			}
		}
	}

	@Override
	public void mouseClicked ( MouseEvent e )
	{
		if (e.getClickCount() >= 2)
		{
			VoxListFiles lista = (VoxListFiles) e.getSource();
			if (!lista.isSelectionEmpty())
			{
				int indice = lista.getSelectedIndex();
				if ((String) lista.getModel().getElementAt(indice).toString() == "..")
				{
					lista.exibeAcima();
				}
				else
				{
					lista.exibeAbaixo(indice);
				}
			}
		}

	}

	@Override
	public void mouseEntered ( MouseEvent arg0 )
	{
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseExited ( MouseEvent arg0 )
	{
		// TODO Auto-generated method stub

	}

	@Override
	public void mousePressed ( MouseEvent arg0 )
	{
		// TODO Auto-generated method stub

	}

	@Override
	public void mouseReleased ( MouseEvent arg0 )
	{
		// TODO Auto-generated method stub

	}
}
